﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using MyLocalChurch.Business;
using MyLocalChurch.Constants;
using MyLocalChurch.Models;
using MyLocalChurch.Models.Enumerations;
using MyLocalChurch.Models.KidsChurch;
using MyLocalChurch.Resources;
using RKConsulting.Helpers;
using RKConsulting.Web.Helpers;

namespace MyLocalChurch.KidsChurch
{
    public partial class CheckOut : System.Web.UI.Page
    {
        private readonly MyContext _context = MyContextSingleton.Instance;
        
        private bool? BarcodeIsGuardian
        {
            get { return ViewState["BarcodeIsGuardian"] as bool?; }
            set { ViewState["BarcodeIsGuardian"] = value; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack)
                return;

            Session[ImageHandler.SessionName] = null;

            BarcodeIsGuardian = null;
            lblMessage.Text = Request.QueryString[QueryParameters.Message] ?? string.Empty;

            Initialize();
        }

        protected void Initialize()
        {
            var guardianId = QueryHelper.GetNullableIntQueryParam(QueryParameters.GuardianId);
            if (guardianId.HasValue)
                InitializeGuardian(guardianId.Value);
            else
            {
                var kidId = QueryHelper.GetNullableIntQueryParam(QueryParameters.KidId);
                if (kidId.HasValue)
                    InitializeKid(kidId.Value);
            }
        }

        protected void InitializeGuardian(int guardianId)
        {
            var guardian = GuardianManager.GetGuardianAndUpdateCache(_context, guardianId);
            if (guardian == null)
                return;

            var barcode = BarcodeManager.GetValidBarcode(guardian.Barcodes);
            if (barcode == null)
                return;

            txtBarcode.Text = barcode.Code;
            ShowGuardianInformation(guardian);
        }

        protected void InitializeKid(int kidId)
        {
            var kid = KidManager.GetKid(_context, kidId);
            if (kid == null)
                return;

            var barcode = BarcodeManager.GetValidBarcode(kid.Barcodes);
            if (barcode == null)
                return;

            txtBarcode.Text = barcode.Code;
            ShowKidInformation(kid);
        }

        protected void txtBarcode_TextChanged(object sender, EventArgs e)
        {
            LoadBarcode();
        }

        protected void btnRefresh_Click(object sender, EventArgs e)
        {
            LoadBarcode();
        }

        protected void LoadBarcode()
        {
            updatePanelGuardian.Visible = false;
            updatePanelKid.Visible = false;
            panelControls.Visible = false;

            BarcodeIsGuardian = null;

            var guardian = GuardianManager.GetGuardianAndUpdateCache(_context, txtBarcode.Text);
            if (guardian != null)
            {
                BarcodeIsGuardian = true;
                ShowGuardianInformation(guardian);
                updatePanelGuardian.Visible = true;
                panelControls.Visible = true;

                return;
            }
            
            var kid = KidManager.GetKid(_context, txtBarcode.Text);
            if (kid != null)
            {
                BarcodeIsGuardian = false;
                ShowKidInformation(kid);
                updatePanelKid.Visible = true;
                panelControls.Visible = true;

                return;
            }

            lblMessage.Text = ValidationMessages.BarcodeNotFound;
        }

        protected void ShowGuardianInformation(Guardian guardian)
        {
            lblGuardianFirstName.Text = guardian.FirstName ?? string.Empty;
            lblGuardianMiddleName.Text = guardian.MiddleName ?? string.Empty;
            lblGuardianLastName.Text = guardian.LastName ?? string.Empty;
            lblGuardianNickName.Text = guardian.NickName ?? string.Empty;
            lblGuardianGender.Text = ((Gender)guardian.Gender).ToString();
            lblGuardianBirthDate.Text = guardian.BirthDate.HasValue
                                            ? guardian.BirthDate.Value.ToString("d")
                                            : string.Empty;
            lblGuardianMobileNumber.Text = guardian.MobileNumber;
            lblGuardianEmailAddress.Text = guardian.EmailAddress;
            txtGuardianAdditionalInformation.Text = guardian.AdditionalInformation;

            if (guardian.Photo != null)
            {
                Session[ImageHandler.SessionName] = guardian.Photo.ImageData;
                var imageHandlerUrl = ConfigurationManager.AppSettings[AppSettingKeys.ImageHandlerUrl];
                guardianImagePreview.ImageUrl = imageHandlerUrl;
            }

            List<Kid> kidsToCheckOut = guardian.Kids
                                               .Where(k => CheckInOutManager.GetCheckInForCheckOut(k.CheckInOuts) != null)
                                               .ToList();
            rptKids.DataSource = kidsToCheckOut;
            rptKids.DataBind();
        }

        protected void ShowKidInformation(Kid kid)
        {
            lblKidFirstName.Text = kid.FirstName ?? string.Empty;
            lblKidMiddleName.Text = kid.MiddleName ?? string.Empty;
            lblKidLastName.Text = kid.LastName ?? string.Empty;
            lblKidNickName.Text = kid.NickName ?? string.Empty;
            lblKidGender.Text = ((Gender)kid.Gender).ToString();
            lblKidBirthDate.Text = kid.BirthDate.ToString("d");
            lblKidCategory.Text = KidManager.GetKidCategory(kid).ToString();
            txtKidAllergies.Text = kid.Allergies;
            lblRelationshipWithGuardian.Text = kid.RelationshipWithGuardian;
            txtKidAdditionalInformation.Text = kid.AdditionalInformation;

            if (kid.Photo != null)
            {
                Session[ImageHandler.SessionName] = kid.Photo.ImageData;
                var imageHandlerUrl = ConfigurationManager.AppSettings[AppSettingKeys.ImageHandlerUrl];
                kidImagePreview.ImageUrl = imageHandlerUrl;
            }
        }

        protected void btnCheckOut_Click(object sender, EventArgs e)
        {
            if (!BarcodeIsGuardian.HasValue)
                return;

            if (BarcodeIsGuardian.Value)
            {
                var guardian = GuardianManager.GetGuardianAndUpdateCache(_context, txtBarcode.Text);
                if (guardian == null)
                    return;

                var count = 0;
                foreach (RepeaterItem item in rptKids.Items)
                {
                    if (item.ItemType != ListItemType.Item && item.ItemType != ListItemType.AlternatingItem)
                        continue;

                    var chkKid = (CheckBox)item.FindControl("chkKid");
                    if (!chkKid.Checked)
                        continue;

                    var hiddenKidId = (HtmlInputHidden) item.FindControl("hiddenKidId");
                    var kidId = int.Parse(hiddenKidId.Value);
                    
                    var kid = KidManager.GetKid(_context, kidId);
                    if (kid == null)
                        continue;
                    
                    var checkIn = CheckInOutManager.GetCheckInForCheckOut(kid.CheckInOuts);
                    if (checkIn == null)
                        continue;

                    checkIn.CheckOutTimeStamp = DateTime.Now;
                    _context.Entry(checkIn).State = EntityState.Modified;

                    count++;
                }

                if (count == 0)
                    lblMessage.Text = string.Format(ValidationMessages.CheckOutNoCheckIns, guardian);
                else
                {
                    _context.SaveChanges();
                    Response.Redirect(
                        string.Concat("CheckOut.aspx?", QueryParameters.Message, "=",
                                      HttpUtility.UrlEncode(string.Format(MyResource.CheckOutGuardianSuccessful,
                                                                          count, guardian))));
                }
            }
            else
            {
                var kid = KidManager.GetKid(_context, txtBarcode.Text);
                if (kid == null)
                    return;

                var category = KidManager.GetKidCategory(kid);
                if (category != KidCategory.PreTeen)
                {
                    lblMessage.Text = ValidationMessages.CheckOutPreTeenOnly;
                    return;
                }

                var checkIn = CheckInOutManager.GetCheckInForCheckOut(kid.CheckInOuts);
                if (checkIn == null)
                    lblMessage.Text = string.Format(ValidationMessages.CheckOutNotCheckedIn, kid);
                else
                {
                    checkIn.CheckOutTimeStamp = DateTime.Now;
                    _context.Entry(checkIn).State = EntityState.Modified;

                    _context.SaveChanges();
                    Response.Redirect(
                        string.Concat("CheckOut.aspx?", QueryParameters.Message, "=",
                                      HttpUtility.UrlEncode(string.Format(MyResource.CheckOutSuccessful, kid))));
                }
            }
        }

        protected void rptKids_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem)
                return;

            var kid = (Kid)e.Item.DataItem;
            
            var hiddenKidId = (HtmlInputHidden)e.Item.FindControl("hiddenKidId");
            hiddenKidId.Value = kid.Id.ToString();

            var lblKidCategoryColumn = (Label)e.Item.FindControl("lblKidCategoryColumn");
            var kidCategory = KidManager.GetKidCategory(kid);
            lblKidCategoryColumn.Text = EnumHelper.ToSpacesString(kidCategory);
        }

        protected void chkKidSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            foreach (RepeaterItem item in rptKids.Items)
            {
                var chkKid = (CheckBox)item.FindControl("chkKid");
                chkKid.Checked = chkKidSelectAll.Checked;
            }
        }
    }
}